#ifndef xpack_test_lang_cxx_make_json_string
#define xpack_test_lang_cxx_make_json_string
#pragma push_macro("xuser")
#undef  xuser
#define xuser mixc::test_lang_cxx_make_json_string::inc
#include"test/helper.hpp" // 需要放第一
#include"interface/ranger.hpp"
#include"interface/seqptr.hpp"
#include"lang/cxx/make_json_string.hpp"
#include"lang/cxx.hpp"
#include"macro/xstr.hpp"
#pragma pop_macro("xuser")

namespace mixc::test_lang_cxx_make_json_string{
    constexpr auto reused_buffer = [](uxx){
        static char buffer[1024 * 4];
        return buffer;
    };

    xstruct(
        xname(type_0)
    ) $

    template<class item_t>
    xstruct(
        xname(type_1),
        xpubf(i, item_t)
    )
        template<class ... args_t>
        type_1(args_t ... args) : i{ args... }{}
    $

    xstruct(
        xname(type_2),
        xpubf(link, type_2 *)
    ) $

    xstruct(
        xname(type_3),
        xpubf(empty0, type_0),
        xpubf(empty1, type_0),
        xpubf(item, type_1<ixx[1]>),
        xpubf(empty_ranger, inc::ranger<ixx>),
        xpubf(empty_seqptr, inc::seqptr<ixx>),
        xpubf(str_ranger, inc::ranger<asciis>),
        xpubf(str_seqptr, inc::seqptr<inc::c08>),
        xpubf(link, type_3 *)
    ) $

    xstruct(
        xname(type_4),
        xpubb(type_1<ixx>),
        xpubf(foo, uxx)
    ) $

    xstruct(
        xname(type_5),
        xpubc(bit0, 1, uxx),
        xpubc(bit1, 1, uxx),
        xpubc(bit2, 1, ixx),
        xpubc(bit3, 1, ixx),
        xpubc(bool0, 1, bool),
        xpubc(bool1, 1, bool)
    ) $

    xtest("make_json_string"){
        // 测试空对象
        {
            type_0 object;
            auto v = inc::c08(inc::make_json_string, object, reused_buffer);
            xassert_eq(v, "{}");
        }

        #define xgen(type,value,expect)     \
        { auto v = inc::c08(inc::make_json_string, type_1<type>{ value }, reused_buffer); xassert_eq(v, expect); }

        xgen(char, '@', xstr({"i":@}))
        xgen(u08, u08(12), xstr({"i":12}));
        xgen(f32, 12.0f, xstr({"i":12}));
        xgen(f32, 12.5f, xstr({"i":12.5}));
        xgen(f64, -12.0, xstr({"i":-12}));
        xgen(f64, -12.5, xstr({"i":-12.5}));
        xgen(asciis, "", xstr({"i":""}));
        xgen(asciis, "hello world", xstr({"i":"hello world"}));
        xgen(inc::c08, "", xstr({"i":""}));
        xgen(inc::c08, "hello world", xstr({"i":"hello world"}));
        xgen(type_0, type_0{}, xstr({"i":{}}));
        xgen(char[6], type_1<char[6]>('h', 'a', 'p', 'p', 'e', '\0'), xstr({"i":"happe"}));
        xgen(ixx[3], type_1<ixx[3]>(1024, 2048, 4096), xstr({"i":[1024,2048,4096]}));

        #undef  xgen

        {
            type_2 temp0{ .link = nullptr };
            type_2 temp1{ .link = & temp0 };

            { auto v = inc::c08(inc::make_json_string, temp0, reused_buffer); xassert_eq(v, xstr({"link":null})); }
            { auto v = inc::c08(inc::make_json_string, temp1, reused_buffer); xassert_eq(v, xstr({"link":{"link":null}})); }
        }

        {
            asciis str_list[] = { "hello", "world" };
            inc::c08 cxx_list[] = { "mixc", "better" };

            auto v = inc::c08(
                inc::make_json_string,
                type_3{
                    .empty0 = {},
                    .empty1 = {},
                    .item = { -1024 },
                    .empty_ranger = {},
                    .empty_seqptr = {},
                    .str_ranger = str_list,
                    .str_seqptr = cxx_list,
                    .link = nullptr
                },
                reused_buffer
            );

            xassert_eq(v, xstr({"empty0":{},"empty1":{},"item":{"i":[-1024]},"empty_ranger":[],"empty_seqptr":[],"str_ranger":["hello","world"],"str_seqptr":["mixc","better"],"link":null}));
        }

        {
            type_4 temp{};
            temp.i = 1234;
            temp.foo = 5678;
            auto v = inc::c08(inc::make_json_string, temp, reused_buffer);
            xassert_eq(v, xstr({"i":1234,"foo":5678}));
        }


        // 测试位域
        {
            type_5 x;
            x.bit0 = 1;
            x.bit1 = 0;
            x.bit2 = 0;
            x.bit3 = -1;
            x.bool0 = false;
            x.bool1 = true;
            auto v = inc::c08(inc::make_json_string, x, reused_buffer);
            xassert_eq(v, xstr({"bit0":1,"bit1":0,"bit2":0,"bit3":-1,"bool0":false,"bool1":true}));
        }
    };
}

#endif
